#ifndef PARSER_ADD_H
#define PARSER_ADD_H

#include <string>
#include <regex>
#include <boost\algorithm\string.hpp>
#include <boost\date_time.hpp>

#include "ParserBase.h"
#include "CommandAdd.h"

using namespace std;
using namespace boost::posix_time;

/**
 * This is the handler for "add" commands. 
 * This class handles all "add" commands, including those from different
 * subtypes - floating, deadline and timed.
 *
 * Note to developer: Parsing here is done with the aid of regular expressions
 * You may wish to modify the constant strings in the CPP file in order to allow
 * a larger range of commands
 @author Ling Chun Kai
*/

class ParserAdd : public ParserBase {
public:
	ParserAdd(ParserBase* _nextParser);
private:
	enum {INSTRUCTION_POS = 1, ARGUMENTS_POS, NUM_MAJOR_SEGMENTS};
	enum CommandType {ADD_FLOATING_TASK, ADD_TIMED_TASK, ADD_DEADLINE_TASK, INVALID};

	// The following are regex constants used for parsing
	static const string regexInstructionAndArguments;
	
	static const string regexArgumentAddTimed;
	static const string regexArgumentAddDeadline;
	static const string regexArgumentAddFloating;

	// The following are the locations for parsed segments for the expressions
	static const int ARGUMENT_POS_ADD_TASKNAME = 1;
	static const int ARGUMENT_POS_ADD_FIRSTTIME = 2;
	static const int ARGUMENT_POS_ADD_SECONDTIME = 3;

	// The following are the keywords allowed for instructions
	static const string regexInstructionAdd;

	bool tryParse(string userCommand, CommandBase*& parsedCommand);

	// This method takes a user command and splits it into the instruction and 
	// argument components
	bool getInstructionAndArguments(const string& userCommand, 
									string& instruction, 
									string& arguments);

	// This method checks that the instruction is of the type 'add'
	bool checkInstruction(const string& instruction);

	// This method parses the arguments provided to an add Instruction
	// and stores them in the PARSED_COMMAND struct passed.
	void parseAdd(CommandBase*& parsedCommand,
				  const string& arguments);

	// The following methods categorize the actual CommandType based on the arguments provided.
	// It returns the appropriate command type. matchingArguments will be 
	// filled up with the relevant details upon successful completion
	CommandType categorizeAddCommand(const string& arguments, smatch& matchingArguments);

	// The following methods fill up the actual PARSED_COMMAND struct 
	// by reading. Additional parsing by individual methods may be required.
	// Returns true if the parsing was a success.
	void makeParsedCommandAddFloatingTask(CommandBase*& parsedCommand, 
										  smatch& matchingArguments);
	void makeParsedCommandAddDeadlineTask(CommandBase*& parsedCommand, 
										  smatch& matchingArguments);
	void makeParsedCommandAddTimedTask(CommandBase*& parsedCommand, 
									   smatch& matchingArguments);
	void makeParsedCommandAddErrorSyntax(CommandBase*& parsedCommand, 
									   smatch& matchingArguments);
};

#endif